home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
satellit
/
pfholes
/
pfholes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-25
|
7KB
|
279 lines
/* Usage: pfholes file1.hol ... fileN.hol
Summarizes the amount of data received and missing in broadcast files.
Written 8-91 by James Dugal, N5KNX
Ver 2, 8-91 jpd (added scan of PG.DIR to obtain file lengths when possible)
-- thanks to pe1chl for code borrowed from pfh.c
Compile by: tcc -O -G -Z -a pfholes.c wildargs.obj
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys\types.h>
#include <dir.h>
/* The SHORT_DIR structure describes the fixed length directory
** entry for the PG.DIR file, version 910207r. The strings (title, source, etc)
** are truncated to fit the structure, if necessary.
** NOTE: types are defined as for the Intel 80x86 architecture; be careful!
*/
struct SHORT_DIR{
unsigned long fnumber;
unsigned long fsize;
unsigned char title[40];
unsigned char source[20];
unsigned char dest[20];
unsigned char keywords[20];
time_t ultime;
unsigned int dlcount;
};
#define SHORT_DIR_SIZE 114
struct dir_entry
{
struct dir_entry *next,*prev;
unsigned long file_id;
unsigned long fsize;
} *entry_list=NULL,*new,*find;
char currpgdir[MAXPATH] = "";
char nomem[] = "Out of memory!";
char fmterr[] = "%s: internal format error";
char *trim(const char *s) /* remove filename's extension & directory parts */
{
char *r,*q;
static char res[256]; /* We can't modify the input string! */
strcpy(res, s);
if ((r=(char *)strrchr(res,'\\')) == NULL) r=res;
else *r++='\0';
if ((q=(char *)strchr(r, '.')) != NULL) *q='\0';
return(r);
}
/* Convert a little-endian (ie, Intel) binary value into an unsigned long */
unsigned long convert_num(cp, len)
unsigned char *cp;
int len;
{
unsigned long val;
int i;
val = 0L;
for (i = 0; i < len; i++)
val |= (unsigned long) *cp++ << (8 * i);
return (val);
}
int readpgdir (filename)
char *filename; /* eg, "PG.DIR" */
{
FILE *dir;
unsigned long file_id;
char data[SHORT_DIR_SIZE+1];
if ((dir = fopen(filename,"rb")) == NULL) /* open the existing dir file */
{
#ifdef DEBUG
perror(filename);
#endif
return 2;
}
/* put dummy item in the list */
if ((entry_list = (struct dir_entry *) malloc(sizeof(struct dir_entry))) == NULL)
{
fprintf(stderr,nomem);
fclose(dir);
return 5;
}
entry_list->next = entry_list->prev = NULL;
entry_list->file_id = (unsigned long)0xffffffffL;
for (;;) /* read all items from directory */
{
/* read dir entry */
if (fread(data,1,SHORT_DIR_SIZE,dir) != SHORT_DIR_SIZE) /* read data */
break;
file_id = convert_num (&data[0], 4); /* file number */
if (file_id == 0)
continue;
/* save this dir entry in a list item */
if ((new = (struct dir_entry *) malloc(sizeof(struct dir_entry))) == NULL)
{
fprintf(stderr,nomem);
fclose(dir);
return 5;
}
new->next = new->prev = NULL;
new->file_id = file_id;
new->fsize = convert_num (&data[4], 4); /* file size */
/* scan the list to find it's place (insertion sort) */
for (find = entry_list; find != NULL; find = find->next)
if (find->file_id > file_id)
{
/* has to be inserted before this one */
if ((new->prev = find->prev) != NULL)
find->prev->next = new;
else
entry_list = new;
new->next = find;
find->prev = new;
break;
}
}
/* Finished with pg.dir file scan; we should be at EOF, else is damaged */
if (!feof(dir))
{
fprintf(stderr,fmterr,filename);
fclose(dir);
return 3;
}
fclose(dir);
#ifdef DEBUG
for (find=entry_list; find != NULL; find=find->next)
{
printf("%lu,%lu\n", find->file_id, find -> fsize);
}
#endif
return 0;
}
unsigned long
getlen(unsigned long fileid) {
for (find=entry_list; find != NULL; find=find->next)
{
if (find->file_id == fileid) return(find -> fsize);
else if (find->file_id > fileid) return(0); /* unknown */
}
return(0); /* unknown */
}
void
free_list(void)
{
for (find=entry_list; find != NULL; )
{ new = find -> next;
free (find);
find = new;
}
entry_list = NULL;
}
void
loadpgdir(const char *holpath) /* Given path to .HOL file, load corresponding PG.DIR */
{
char path[MAXPATH], drive[MAXDRIVE], dir[MAXDIR];
(void)fnsplit(holpath, drive, dir, NULL, NULL);
fnmerge(path, drive, dir, "PG", ".DIR");
if (strcmp(path, currpgdir) == 0) return; /* Same PG.DIR as last time */
if (currpgdir[0]) free_list(); /* different PG.DIR, free mem holding previous PG.DIR */
strcpy(currpgdir, path); /* make new one current */
if (readpgdir(currpgdir)) return; /* error, can't read PG.DIR */
}
void main(int argc, char *argv[])
{
FILE *f;
int i,h;
unsigned hcnt, hrcnt, linecnt;
unsigned long from, to, prev_to, prev_need, got, need, maxlen, filenum;
char me[MAXFILE];
char buf[256], *filenm;
strcpy(me, trim(argv[0]));
if (argc == 1) {
printf("Usage: %s file1.hol ... fileN.hol\n"
"\tsummarizes amount of bytes received and missing from bcst files.\n",
me);
exit(1);
}
printf("FILE\t\tSIZE\tHOLES\tHAVE\tNEED\n");
for (i=1; i<argc; i++) {
filenm=trim(argv[i]);
(void)sscanf(filenm,"%lX", &filenum);
printf("\n%s\t\t", filenm);
if ((f=fopen(argv[i], "r")) == NULL) {
perror(me);
continue;
}
loadpgdir(argv[i]); /* build list of PG.DIR's interesting contents */
linecnt=0;
if (fgets(buf, sizeof(buf), f) == NULL) goto bad_fmt;
linecnt++;
if (sscanf(buf, "%u pfh header received\n", &hrcnt) != 1) goto bad_fmt;
if (fgets(buf, sizeof(buf), f) == NULL) goto bad_fmt;
linecnt++;
if (sscanf(buf, "%lu pfh file length\n", &maxlen) != 1) goto bad_fmt;
if (maxlen == 0L) maxlen = getlen(filenum); /* use value from PG.DIR */
if (fgets(buf, sizeof(buf), f) == NULL) goto bad_fmt;
linecnt++;
if (sscanf(buf, "%u holes\n", &hcnt) != 1) {
bad_fmt: if (errno) perror(me);
fprintf(stderr, "%s: Data in unexpected format near line %u.", argv[i], linecnt);
fclose(f);
continue;
}
got = need = prev_to = 0L;
for (h=0; h<hcnt; h++) {
if (fgets(buf, sizeof(buf), f) == NULL) goto bad_fmt;
linecnt++;
if (sscanf(buf, "%lu, %lu\n", &from, &to) != 2) goto bad_fmt;
if (from) {
got += from - prev_to -1;
if (!prev_to) got++;
}
if (h == (hcnt-1) && maxlen) to = min(maxlen-1, to); /* correct last hole's length */
prev_need = need;
need += to - from + 1;
prev_to= to;
}
if (maxlen == 0L)
printf ("?\t%u\t%lu\t>%lu", hcnt, got, prev_need);
else printf ("%lu\t%u\t%lu\t%lu", maxlen, hcnt, got, need);
fclose(f);
}
printf("\n");
}